﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows.Input;
using GC_FFW.BusinessEntities.Forecast;
using GC_FFW.ForecastWriterClient.Helpers;
using GC_FFW.ForecastWriterClient.ViewModels.Parameters;

namespace GC_FFW.ForecastWriterClient.ViewModels
{
	public class MatchEventsEditorViewModel : INotifyPropertyChanged
	{
		#region Variables

		private readonly MatchEventsEditorViewModelParameters _parameters;

		private bool _isWindowEnabled;
		private string _homeTeamName;
		private string _homeTeamGoalsCount;
		private string _awayTeamName;
		private string _awayTeamGoalsCount;
		private string _status;
		private DateTime _matchDate;

		private RelayCommand _saveCommand;

		#endregion

		#region Properties

		public string HomeTeamName
		{
			get { return _homeTeamName; }
			set
			{
				_homeTeamName = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("HomeTeamName"));
			}
		}

		public string HomeTeamGoalsCount
		{
			get { return _homeTeamGoalsCount; }
			set
			{
				_homeTeamGoalsCount = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("HomeTeamGoalsCount"));
			}
		}

		public string AwayTeamName
		{
			get { return _awayTeamName; }
			set
			{
				_awayTeamName = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("AwayTeamName"));
			}
		}

		public string AwayTeamGoalsCount
		{
			get { return _awayTeamGoalsCount; }
			set
			{
				_awayTeamGoalsCount = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("AwayTeamGoalsCount"));
			}
		}

		public DateTime MatchDate
		{
			get { return _matchDate; }
			set
			{
				_matchDate = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("MatchDate"));
			}
		}

		public string Status
		{
			get { return _status; }
			set
			{
				_status = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("Status"));
			}
		}

		public bool IsWindowEnabled
		{
			get { return _isWindowEnabled; }
			set
			{
				_isWindowEnabled = value;
				if (PropertyChanged == null) return;
				PropertyChanged(this, new PropertyChangedEventArgs("IsWindowEnabled"));
			}
		}

		public List<GoalsViewModelItem> Goals { get; set; }

		public ICommand SaveCommand
		{
			get { return _saveCommand; }
		}

		#endregion

		#region Constructors

		public MatchEventsEditorViewModel(MatchEventsEditorViewModelParameters parameters)
		{
			if (parameters == null)
				throw new ArgumentNullException(string.Format("Parameters"));
			_parameters = parameters;

			if (_parameters.SoccerfameDataHelperFactory == null)
				throw new ArgumentNullException(string.Format("SoccerfameDataHelperFactory"));

			FillViewModel();
		}

		#endregion

		#region Internal Implementation

		private void FillViewModel()
		{
			_saveCommand = new RelayCommand(Save);
			Status = string.Format("Loading Process...");

			var worker = new BackgroundWorker();
			worker.DoWork += FillViewModel_DoWork;
			worker.RunWorkerCompleted += FillViewModel_DoWorkComplete;
			worker.RunWorkerAsync();
		}

		private void FillViewModel_DoWork(object sender, DoWorkEventArgs e)
		{
			if (_parameters.Match == null) return;

			HomeTeamName = _parameters.Match.HomeTeamName;
			AwayTeamName = _parameters.Match.AwayTeamName;

			HomeTeamGoalsCount = _parameters.Match.HomeTeamGoalsCount.ToString(CultureInfo.InvariantCulture);
			AwayTeamGoalsCount = _parameters.Match.AwayTeamGoalsCount.ToString(CultureInfo.InvariantCulture);

			MatchDate = _parameters.Match.Date;

			if (_parameters.Match.Goals != null)
				Goals = _parameters.Match.Goals.Select(g =>
					new GoalsViewModelItem
					{
						IsHomeTeamGoal = g.IsHomeTeamGoal,
						Name = g.Goalscorer,
						Time = g.Time
					}).ToList();
		}

		private void FillViewModel_DoWorkComplete(object sender, RunWorkerCompletedEventArgs e)
		{
			Status = string.Empty;
			IsWindowEnabled = true;
		}

		private void Save(object parameter)
		{
			IsWindowEnabled = false;
			Status = "Saving Process...";

			var worker = new BackgroundWorker();
			worker.DoWork += Save_DoWork;
			worker.RunWorkerCompleted += Save_DoWorkComplete;
			worker.RunWorkerAsync();
		}

		private void Save_DoWork(object sender, DoWorkEventArgs e)
		{
			var match = new Match
			{
				HomeTeamName = HomeTeamName,
				AwayTeamName = AwayTeamName,
				Date = MatchDate
			};

			if (_parameters.Match != null && _parameters.Match.HomeTeamName != HomeTeamName
				&& _parameters.SoccerfameDataHelperFactory.TeamNamesService != null)
				_parameters.SoccerfameDataHelperFactory.TeamNamesService.Save(HomeTeamName, _parameters.Match.HomeTeamName);

			if (_parameters.Match != null && _parameters.Match.AwayTeamName != AwayTeamName
				&& _parameters.SoccerfameDataHelperFactory.TeamNamesService != null)
				_parameters.SoccerfameDataHelperFactory.TeamNamesService.Save(AwayTeamName, _parameters.Match.AwayTeamName);

			int num;
			int.TryParse(HomeTeamGoalsCount, out num);
			match.HomeTeamGoalsCount = num;
			int.TryParse(AwayTeamGoalsCount, out num);
			match.AwayTeamGoalsCount = num;

			match.Goals = (Goals ?? new List<GoalsViewModelItem>())
				.Select(g => new Goal
				{
					Goalscorer = g.Name,
					IsHomeTeamGoal = g.IsHomeTeamGoal,
					Time = g.Time
				})
				.ToList();

			if (_parameters.Match != null && _parameters.Match.Goals != null)
			{
				foreach (var goal in match.Goals)
				{
					var goalOriginal = _parameters.Match.GetGoalByTime(goal.Time);
					if (goalOriginal != null && goalOriginal.Goalscorer != goal.Goalscorer
						&& _parameters.SoccerfameDataHelperFactory.PlayerNamesService != null)
						_parameters.SoccerfameDataHelperFactory.PlayerNamesService.Save(goal.Goalscorer, goalOriginal.Goalscorer);
				}
			}

			if (_parameters.UpdateAction != null)
				_parameters.UpdateAction(match);
		}

		private void Save_DoWorkComplete(object sender, RunWorkerCompletedEventArgs e)
		{
			Status = string.Format("Saving Process Completed");
			IsWindowEnabled = true;
		}

		#endregion

		#region INotifyPropertyChanged Members

		public event PropertyChangedEventHandler PropertyChanged;

		protected virtual void OnPropertyChanged(string propertyName)
		{
			var handler = PropertyChanged;
			if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
		}

		#endregion
	}
}
